import {messages} from "share/common";
import React from 'react';
import { Select, Spin } from 'antd'
const Option = Select.Option;

import selectorData from 'share/selectorData'
import httpFetch from 'share/httpFetch'
import debounce from 'lodash.debounce';
/**
 * 选择表单组件，由antd的select组件改造而来
 * 使用需与share/selectorData.js内的数据一起使用
 *
 * 2018/11/26 zaranengap
 * 这个组件是个封装好接口的Select
 * 考虑了加载状态、各种形态的默认值、没有加载数据时的假数据
 * 跟Chooser相比不知道精简了多少
 * 我还主动在search-area里加了支持
 * 特别好用，还支持各种情况
 * 算是我比较满意的组件
 * 可是为啥感觉用的人很少？
 * 答：因为显示的字段少
 *
 */
class Selector extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      value: undefined,
      selectValue: undefined,
      fetched: false,  //是否已经得到结果
      options: [],
      selectorItem: {}
    };
    this.sourceData = [];  //储存原始数据数组
    this.handleSearch = debounce(this.handleSearch, 250);
  }

  componentDidMount(){
    const { type, selectorItem, value } = this.props;
    //设置selectorItem
    if(selectorItem){
      this.setState({ selectorItem }, () => this.setValue(value))
    }
    else if(type){
      let item = selectorData[type];
      this.setState({ selectorItem: item }, () => this.setValue(value))
    }
  }

  /**
   * 设置Select的值
   * @param valueWillSet 将要设置的值
   */
  setValue = (valueWillSet) => {
    let { value, options, selectorItem } = this.state;
    if(valueWillSet) {
      if (typeof valueWillSet === 'string' && valueWillSet !== value) {
        this.setState({value: valueWillSet})
      } else if (typeof valueWillSet === 'object') {
        if (valueWillSet === null) {
          this.setState({value: []})
        } else {
          let tempOptions = options;
          let tempValue = JSON.parse(JSON.stringify(valueWillSet));
          const { key, label } = selectorItem;
          if(!tempValue.key) {
            tempValue.key = tempValue[key]
          }
          if(!tempValue.label) {
            console.log('tempValue.label', tempValue)
            tempValue.label = typeof label === 'string' ? tempValue[label] : label(tempValue)
          }
          //如果options里没有值，则为options加上这个值，设置temp: true
          if (tempOptions.length === 0 || valueWillSet.optionsChange) {
            tempValue.temp = true;
            tempOptions = [tempValue]
          }
          this.setState({options: tempOptions, value: tempValue.key})
        }
      }
    }
    else{
      this.setState({value: []})
    }
  };

  /**
   * value为传入值
   * @param nextProps
   */
  componentWillReceiveProps = (nextProps) => {
    this.setValue(nextProps.value);
    if (nextProps.selectorItem && nextProps.selectorItem.dynamicUrl) {
      this.setState({selectorItem: nextProps.selectorItem});
    } else if (nextProps.type) {
      const item = selectorData[nextProps.type];
      this.setState({ selectorItem: item })
    }
  };

  /**
   * 设置Select的Options
   * @param data
   */
  setOptions = (data) => {
    const { selectorItem } = this.state;
    const { filter, type } = this.props;
    let list;
    if(selectorItem.listKey){
      let keys = selectorItem.listKey.split('.');
      list = data;
      keys.map(key => {
        list = list[key];
      })
    } else {
      list = data;
    }
    let resultOptions = [];
    list.map(item => {
      let option = {
        key: item[selectorItem.key],
        label: typeof selectorItem.label === 'string' ? item[selectorItem.label] : selectorItem.label(item),
        showSearchLabel: selectorItem.showSearchLabel ? typeof selectorItem.showSearchLabel === 'string' ? item[selectorItem.showSearchLabel] : selectorItem.showSearchLabel(item) : null
      };
      if (type === 'forDriver') {
        option.userOID = item[selectorItem.userOID]; // forDriver: selectorItem.userOID: 'userOID'
        option.vendor = item.vendor;
      }
      filter(item) && resultOptions.push(option);
    });
    this.sourceData = list;
    this.setState({ options: resultOptions, fetched: true })
  };

  //得到焦点时的回调
  handleFocus = () => {
    const { options, selectorItem, fetched, value } = this.state;
    this.setState({focusState:true})
    //如果存在searchKey，则为搜索模式，不触发handleFocus
    if(!fetched && selectorItem.searchKey){
      // value可能是 undefined 或 []
      if (this.props.searchIfKeywordIsNull && (!value || !value.length)) {
        this.handleSearch()
      } else {
        this.setState({ fetched: true })
      }
    }
    // url动态修改情况下 每次获取新的options数据
    if (selectorItem.dynamicUrl) {
      httpFetch.get(selectorItem.url, this.props.params).then(res => {
        this.setOptions(res.data);
      });
      return !1;
    }
    //如果接口尚未调用 且 options没有值或只有设置的默认值时 且 不为搜索模式 时
    if(!fetched && (options.length === 0 || (options.length === 1 && options[0].temp)) && !selectorItem.searchKey){
      httpFetch.get(selectorItem.url, this.props.params).then(res => {
        this.setOptions(res.data);
      })
    }
    else{
      if(selectorItem.offlineSearchMode && (options.length === 0 || (options.length === 1 && options[0].temp))){
        httpFetch.get(selectorItem.url, this.props.params).then(res => {
          this.setOptions(res.data);
        })
      }
    }
  };

  //失去焦点
  handleBlur = () => {
    this.setState({ focusState: false });
    const { value, selectValue } = this.state;
    const { entity } = this.props;
    const onChange = this.props.onChange;
    if (value !== selectValue && !entity) { //失去焦点时，若未选择option，则输入框置空 bug14413
      //非对象可以用!==判断，对象的话要另外处理
      this.setState({ value: undefined, selectValue: undefined })
      if (onChange) {
        onChange(undefined);
      }
    }
  };

  onSelect = (changedValue, option) => {
    this.setState({focusState: false})
    let target = changedValue;
    //如果需要整个对象，则遍历原始数据列表
    if (this.props.entity) {
      this.sourceData.map(data => {
        if (data[this.state.selectorItem.key] === changedValue)
          target = data;
      })
    }
    const onChange = this.props.onChange;
    this.setState({value: changedValue, selectValue: changedValue});
    if (onChange) {
      onChange(target, option.props);
    }
  };

  onChange = (changedValue) => {
    const onChange = this.props.onChange;
    this.setState({value: changedValue});
    if(!changedValue) {
      onChange(changedValue);
    }
  };

  //搜索时的回调
  handleSearch = (key) => {
    const { selectorItem } = this.state;
    this.setState({ focusState: true });
    if(selectorItem.offlineSearchMode){
      return;
    }
    this.setState({ fetched: false, value: key });
    if(key || this.props.searchIfKeywordIsNull){
      let params = this.props.params;
      //参数内加上对应的searchKey
      if(!params)
        params = {};
      params[selectorItem.searchKey] = key;
      httpFetch.get(selectorItem.url, params).then(res => {
        this.setOptions(res.data);
      })
    } else {
      this.setState({ options: [], fetched: true })
    }
  };

  dropdownVisibleChange = () => {
    this.setState({ focusState: true })
  };

  render() {
    const { value, options, fetched, selectorItem, focusState } = this.state;
    const { disabled, placeholder, showSearch, allowClear, getPopupContainer,size } = this.props;
    return (
      <Select
        allowClear={allowClear}
        showSearch={showSearch}
        style={{ width: '100%' }}
        mode={ (!showSearch&&(selectorItem.searchKey || selectorItem.offlineSearchMode)) ? 'combobox' : null}
        placeholder={placeholder}
        onFocus={this.handleFocus}
        onBlur={this.handleBlur}
        size={size}
        value={value}
        onSearch={this.handleSearch}
        onChange={this.onChange}
        disabled={disabled}
        onSelect={this.onSelect}
        getPopupContainer={getPopupContainer}
        onDropdownVisibleChange={this.dropdownVisibleChange}
        filterOption={selectorItem.offlineSearchMode ? (input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 : false}
        optionLabelProp="children"
        notFoundContent={fetched ? messages('components.key410'/*无匹配结果*/) : <Spin size="small"/>}
      >
        {options.map(option => {
          if (this.props.type === 'forDriver') {
            // 因为司机的审批人会重复，所以userOID会重复，所以加一个key作为value的前缀
            return (
              <Option key={option.key} value={`${option.key},${option.userOID},${option.vendor}`} style={{whiteSpace: 'unset'}}>
                {focusState ? option.showSearchLabel || option.label : option.label}
              </Option>
            )
          }
          return (
            <Option key={option.key} value={option.key} style={{whiteSpace: 'unset'}}>
              {focusState ? option.showSearchLabel || option.label : option.label}
            </Option>
          )
        })}
      </Select>
    );
  }
}

Selector.propTypes = {
  type: React.PropTypes.string,  //Selector类型，见share/selectorData.js
  selectorItem: React.PropTypes.object,  //如果selector类型不能满足要求，则可以自定义selectorItem，格式同type对应对象
  params: React.PropTypes.object,  //调用接口的时候添加的参数
  disabled: React.PropTypes.bool,  //是否可用
  showSearch: React.PropTypes.bool,  //是否搜索模式，只支持单选模式
  allowClear: React.PropTypes.bool,  //是否允许清除
  value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.object]),  //组件值，可为字符串或对象，若为对象则格式为{label, key}
  placeholder: React.PropTypes.string,
  entity: React.PropTypes.bool,  //是否需要整个对象，如果为true则返回选择的整个对象，如果为false则只返回对应key值
  onChange: React.PropTypes.func,
  filter: React.PropTypes.func, //过滤规则，接收原始数据对象，返回为true则显示，为false则不显示
  size: React.PropTypes.string,
  searchIfKeywordIsNull: React.PropTypes.bool, //关键字为空时是否需要请求接口搜索
};

Selector.defaultProps = {
  disabled: false,
  showSearch:false,
  allowClear:true,
  placeholder: messages('common.select')/*"请选择"*/,
  entity: false,
  getPopupContainer: triggerNode => triggerNode.parentNode, // 项对滚动的节点元素
  filter: option => true,
  size: 'default',
  searchIfKeywordIsNull: false
};

Selector.getSelectorData = type => selectorData[type];

export default Selector;
